#include	<stdint.h>

#ifndef CONFIG_PARSER_H
#define CONFIG_PARSER_H

typedef uint8_t node_id_t;
typedef struct config_info_t config_info;
typedef struct server_info_t server_info;
typedef struct proposer_info_t proposer_info;
typedef struct learner_info_t learner_info;
typedef struct proxy_info_t proxy_info;
typedef struct learner_acceptor_t learner_acceptor;

//---------------------------------------STRUCTS--------------------------------------------------
struct learner_acceptor_t {

	node_id_t learner_id;
	node_id_t acceptor_id;
	int acceptor_port;
	int learner_tcp_sid;

};
//-------------------------------------------------------------
struct server_info_t {

	node_id_t server_id;

	char ip[16];
	int port;

	int self_sid;
	int successor_sid;
	int proposer_recv_sid; // only for the multicast sender.

	struct sockaddr_in ring_successor_addr;
	struct sockaddr_in ring_self_addr;

	int send_learner_0_sid;

	learner_acceptor learner_tcp_acceptor[MAX_LEARNERS];

};
//-------------------------------------------------------------  
struct learner_info_t {

	node_id_t learner_id;
	char ip[16];
	int port;

	int self_sid; //The receive socket to get packets
	int successor_sid; //The socket to which the learner forwards the packet

	struct sockaddr_in address; // can be used in the line as well, but I am not using it now.

	struct sockaddr_in ring_self_address; 	   // can be used in the line as well
	struct sockaddr_in ring_successor_address; // can be used in the line as well

};
//-------------------------------------------------------------  
struct proposer_info_t {
	node_id_t proposer_id;
	int proposer_to_acceptor_0_port;
	int proposer_to_acceptor_0_sid;
};
//-------------------------------------------------------------  

struct config_info_t {

	node_id_t self_proposer_id; // in case the node is proposer
	node_id_t self_learner_id; // in case the node is learner
	node_id_t self_acceptor_id; // in case the node is acceptor

	int total_num_acceptors;
	int total_num_learners;
	int total_num_proposers;
	int total_num_proxies;

	server_info server_infos[MAX_ACCEPTORS];
	learner_info learner_infos[MAX_LEARNERS];
	proposer_info proposer_infos[MAX_PROPOSERS];
	learner_acceptor learner_to_acceptor[MAX_LEARNERS];

	int learner_tcp_sid_count;
	int learner_to_acceptor_sid; // used for learner

	int ring_size;
};

void parse_configuration(const char * config_path, int acceptor_id, int proposer_id, int learner_id);
void get_ip_port(const char* config_file, config_info * config, const char * match, char flag);
void get_multicast_address(const char* config_file, config_info * config, const char * match);
void get_acceptor_0_address_for_proposer(const char* config_file, config_info * config, const char * match);
void read_a_number(const char* config_file, config_info * config, const char * match);
config_info* get_config_info();

void create_socket_for_proposer(config_info *config);
void create_socket_for_learner_tcp_acceptor(config_info *config);
void create_socket_acceptor_ring(config_info *config);
void create_socket_for_acceptor_tcp_learner(config_info *config);
void create_socket_lp_ring(config_info *config);
int  find_learner_given_ip(config_info *config, char ip[INET_ADDRSTRLEN]);
int  find_learner_index_given_id(config_info *config, int learner_id, int server_id);

int GET_ACCEPTOR_SELF_SID_RING(int id);
int GET_ACCEPTOR_SUCCESSOR_SID_RING(int id);
int GET_ACCEPTOR_0_SID_UDP_FROM_PROPOSER(int id);
int GET_ACCEPTOR_SID_TCP_FROM_LEARNER(int server_id,  int nth_learner);
int GET_ACCEPTOR_SID_UDP_TO_LEARNER_0(int id);

int GET_LEARNER_SID_UDP_FROM_PREDECESSOR(int id);
int GET_LEARNER_SID_TCP_TO_ACCEPTOR();

int GET_PROPOSER_SID_UDP_TO_ACCEPTOR_0(int id);

struct sockaddr_in* GET_SOCKADDR();

#endif
